package com.ywj.demo03_synchronized_nature;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
    目标：演示Lock不可中断和可中断
 */
public class Demo03_Interruptible {
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
//        test01();
//        test02();
        test03();
    }

    //演示Lock不可中断 lock()方法
    public static void test01() throws InterruptedException {
        Runnable run = () -> {
            String name = Thread.currentThread().getName();
            try {
                lock.lock();   //该方式不可被中断，lock()方法无返回值
                System.out.println(name + "获得锁，进入锁执行");
                Thread.sleep(88888);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println(name + "释放锁");
            }
        };

        Thread t1 = new Thread(run);
        t1.start();
        Thread.sleep(1000);
        Thread t2 = new Thread(run);
        t2.start();

        System.out.println("停止t2线程前");
        t2.interrupt();
        System.out.println("停止t2线程后");
        Thread.sleep(1000);
        System.out.println(t1.getState());
        System.out.println(t2.getState());
    }


//Thread-0获得锁,进入锁执行；Thread-1在指定时间没有得到锁，做其他操作
    //演示Lock可中断
    public static void test02() throws InterruptedException {
        Runnable run = () -> {
            String name = Thread.currentThread().getName();
            boolean b = false;
            try {
                //tryLock在指定时间内 会尝试能否得到锁，能得到 返回true，不能得到 返回false
                b = lock.tryLock(3, TimeUnit.SECONDS);
                if (b) {
                    System.out.println(name + "获得锁,进入锁执行");
                    Thread.sleep(88888);
                } else {
                    System.out.println(name + "在指定时间没有得到锁，做其他操作");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (b) {
                    lock.unlock();
                    System.out.println(name + "释放锁");
                }
            }

        };
        Thread t1 = new Thread(run);
        t1.start();
        Thread.sleep(1000);
        Thread t2 = new Thread(run);
        t2.start();

        // System.out.println("停止t2线程前");
        // t2.interrupt();
        // System.out.println("停止t2线程后");
        //
        // Thread.sleep(1000);
        // System.out.println(t1.getState());
        // System.out.println(t2.getState());
    }


    public static void test03() throws InterruptedException {
        Runnable run = () -> {
            String name = Thread.currentThread().getName();
            try {
                System.out.println(name + "尝试获取锁");
                //如果没有竞争 该方法就会获取lock对象锁；如果有竞争就进入阻塞队列，可以被其它线程用interruput方法打断
                lock.lockInterruptibly();
                System.out.println("1 " + Thread.currentThread().getName() + ": " + Thread.currentThread().getState());
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("2 " + Thread.currentThread().getName() + ": " + Thread.currentThread().getState());
//                System.out.println(name + "没有获得锁，被打断。return");
            }

            try {
                System.out.println("3 " + Thread.currentThread().getName() + ": " + Thread.currentThread().getState());
                System.out.println(name + "获得锁");
            } finally {
                lock.unlock();
                System.out.println("4 " + Thread.currentThread().getName() + ": " + Thread.currentThread().getState());
            }

        };

        //t1启动前，主线程先获得了锁
        lock.lock();
        Thread t1 = new Thread(run);
        t1.start();
        System.out.println("主线程sleep前 :" + t1.getName() + "-" + t1.getState() + ",  当前线程" + Thread.currentThread().getName() + "-" + Thread.currentThread().getState());
        Thread.sleep(1000);
        System.out.println("主线程sleep后 :" + t1.getName() + "-" + t1.getState() + ",  当前线程" + Thread.currentThread().getName() + "-" + Thread.currentThread().getState());
        t1.interrupt();
        System.out.println("调用t1.interrupt()后 :" + t1.getName() + "-" + t1.getState() + ",  当前线程" + Thread.currentThread().getName() + "-" + Thread.currentThread().getState());


    }

}
